#ifndef ERROSCONTEINER_H_
#define ERROSCONTEINER_H_

#include "Defines.h"

/*-----------------------------------------------------------------------------
 *  Tipos de erros
 *-----------------------------------------------------------------------------*/
typedef enum
{
    ERR_LEX, // Erro léxico
    ERR_SIN, // Erro sintático
    ERR_SEM  // Erro semântico
} ErrorType;

/*-----------------------------------------------------------------------------
 *  Mensagem específica do erro
 *-----------------------------------------------------------------------------*/
typedef enum
{
    LEX_UNKNOWN = 4, // Símbolo não permitido
    LEX_MF_INTEGER,  // Número inteiro mal formado
    LEX_MF_REAL,     // Número real mal formado
    LEX_MF_ID,       // Identificador mal formado
    LEX_EMP_CHAR,    // Caracter vazio
    LEX_OS_CHAR,     // Caracter muito grande
    LEX_QMNC_CHAR,   // Aspas simples não fechada
    LEX_QMNC_STRING, // Aspas dupla não fechada
    LEX_BCNC,        // Comentário de bloco não fechado
    LEX_LONG_ID,     // Identificador muito longo

    SIN_SEMICOLON_EXPECTED, // ; esperado
    SIN_ID_EXPECTED,        // identificador esperado
    SIN_BEGIN_EXPECTED,     // begin esperado
    SIN_END_EXPECTED,       // end esperado
    SIN_EQUAL_EXPECTED,     // = esperado
    SIN_COLON_EXPECTED,     // : esperado
    SIN_TYPE_EXPECTED,      // tipo de variável esperado
    SIN_LPAREN_EXPECTED,    // ( esperado
    SIN_RPAREN_EXPECTED,    // ) esperado
    SIN_NUMBER_EXPECTED,    // número esperado
    SIN_RELATION_EXPECTED,  // relação esperada
    SIN_OPERATOR_EXPECTED,  // operador esperado
    SIN_FACTOR_EXPECTED,    // fator esperado
    SIN_RETURN_EXPECTED,    // return esperado
    SIN_DOT_EXPECTED,       // . esperado
    SIN_PROGRAM_EXPECTED,   // program esperado
    SIN_UNTIL_EXPECTED,     // until esperado
    SIN_THEN_EXPECTED,      // then esperado
    SIN_ASSIGN_EXPECTED,    // := ou ( esperado
    SIN_DO_EXPECTED,        // do esperado

    SIN_INVALID_CMD,        // comando inválido

    SIN_SEMICOLON,      // ; sincronismo
    SIN_COLON,          // : sincronismo
    SIN_DOT,            // . sincronismo
    SIN_BEGIN,          // begin sincronismo
    SIN_END,            // end sincronismo
    SIN_EQUAL,          // = sincronismo
    SIN_RETURN,         // return sincronismo
    SIN_RPAREN,         // ) sincronismo

    SIN_SYN_TOKEN,      // mensagem que informa até que símbolo será pulado
    SIN_SKIPPED,        // mensagem que informa que símbolo foi pulado

    SEM_ALREADY_DECLARED,  // identificador já declarado
    SEM_VAR_NOT_DECLARED,  // variável não declarada
    SEM_PROC_NOT_DECLARED, // procedimento não declarado
    SEM_CONST_ATTRIB,      // atribuição em constante
    SEM_PARAMETERS_ERROR,  // incompatibilidade de parâmetros
    SEM_ATTRIBUTION,       // atribuição de real à inteiro
    SEM_DIVISION,          // divisão de dois números não inteiros
    SEM_READLN_WRITELN     // argumentos com tipos diferentes em readln e writeln

} ErrorWhat;

namespace LALG
{

/*
 * =====================================================================================
 *        Class:  ErrorPrinter
 *  Description:  Classe que representa um contêiner de erros encontrados no programa
 * =====================================================================================
 */
class ErrorPrinter
{

public:

    /*-----------------------------------------------------------------------------
     *  Constrói um novo contêiner de erros
     *-----------------------------------------------------------------------------*/
    ErrorPrinter();

    /*-----------------------------------------------------------------------------
     *  Imprime um erro/aviso
     *-----------------------------------------------------------------------------*/
    void print(int lineno, ErrorType type, ErrorWhat what, string text, int synToken = 0);

    /*-----------------------------------------------------------------------------
     *  Informa se já ocorreu algum erro
     *-----------------------------------------------------------------------------*/
    bool happened;

private:

    /*-----------------------------------------------------------------------------
     *  Estrutura para armazenar as mensagens de saídas para cada erro
     *-----------------------------------------------------------------------------*/
    unordered_map<int, string> name;

};

}

#endif /* ERROSCONTEINER_H_ */
